package com.example.my_bookkeeping;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.longClick;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;

import static org.hamcrest.Matchers.allOf;

import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import androidx.recyclerview.widget.RecyclerView;
import androidx.test.espresso.ViewInteraction;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;

import com.example.my_bookkeeping.data.manager.BookKeepManager;
import com.example.my_bookkeeping.data.manager.UserManager;
import com.example.my_bookkeeping.data.user.BookKeep;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class EditBookKeepTest {

    @Rule
    public ActivityScenarioRule<MainActivity> mActivityScenarioRule =
            new ActivityScenarioRule<>(MainActivity.class);

    private UserManager userManager;
    private BookKeepManager bookKeepManager;

    @Before
    public void setUp() {
        userManager = UserManager.getInstance();
        // 清空所有账目，确保测试环境干净
        userManager.reset();
        bookKeepManager = BookKeepManager.getInstance();
    }

    @After
    public void tearDown() {
        userManager.reset();
    }

    @Test
    public void testEditBookKeep() throws InterruptedException {
        // 添加一个测试账目
        bookKeepManager.add("2024-03-15", 50.0, "交通", "公交车", false);

        // 切换到账目管理页面
        ViewInteraction bottomNavigationItemView = onView(
                allOf(withId(R.id.item_bookkeep), withContentDescription("账目管理"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.bottom_navigation_view),
                                        0),
                                3),
                        isDisplayed()));
        bottomNavigationItemView.perform(click());

        Thread.sleep(2000); // 等待页面加载

        // 长按第一个账目条目
        ViewInteraction recyclerView = onView(
                allOf(withId(R.id.recyclerView_record),
                        childAtPosition(
                                withId(R.id.itemsCard),
                                0)));
        recyclerView.perform(actionOnItemAtPosition(0, longClick()));

        // 点击弹出菜单中的"修改"
        onView(allOf(withId(android.R.id.title), withText("修改")))
                .perform(click());

        // 在修改对话框中输入新的信息
        onView(withId(R.id.et_amount)).perform(replaceText("150.0"), closeSoftKeyboard());
        onView(withId(R.id.et_category)).perform(replaceText("购物"), closeSoftKeyboard());
        onView(withId(R.id.et_remark)).perform(replaceText("买衣服"), closeSoftKeyboard());

        // 点击"确定"按钮
        onView(allOf(withId(android.R.id.button1), withText("确定")))
                .perform(click());

        Thread.sleep(2000); // 等待数据更新和界面刷新

        // 验证界面上显示的账目信息已更新
        onView(withRecyclerView(R.id.recyclerView_record).atPositionOnView(0, R.id.tv_amount))
                .check(matches(withText("150.0")));
        onView(withRecyclerView(R.id.recyclerView_record).atPositionOnView(0, R.id.tv_category))
                .check(matches(withText("购物")));
        onView(withRecyclerView(R.id.recyclerView_record).atPositionOnView(0, R.id.tv_remark))
                .check(matches(withText("买衣服")));

        // 验证UserDataStore中的数据已更新
        ArrayList<BookKeep> updatedBookKeeps = bookKeepManager.getAll();
        assert updatedBookKeeps.size() == 1;
        BookKeep updatedBookKeep = updatedBookKeeps.get(0);
        assert updatedBookKeep.getAmount() == 150.0;
        assert updatedBookKeep.getCategory().equals("购物");
        assert updatedBookKeep.getRemark().equals("买衣服");
        assert !updatedBookKeep.getIsIncome(); // 收支类型应该不变
        // assert updatedBookKeep.getTime().equals("2024-03-15"); // 时间应该不变
    }

    // Helper method to find a view within a RecyclerView item
    public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) {
        return new RecyclerViewMatcher(recyclerViewId);
    }

    // Helper method to find a child view at a specific position
    private static Matcher<View> childAtPosition(
            final Matcher<View> parentMatcher, final int position) {

        return new TypeSafeMatcher<View>() {
            @Override
            public void describeTo(Description description) {
                description.appendText("Child at position " + position + " in parent ");
                parentMatcher.describeTo(description);
            }

            @Override
            public boolean matchesSafely(View view) {
                ViewParent parent = view.getParent();
                return parent instanceof ViewGroup && parentMatcher.matches(parent)
                        && view.equals(((ViewGroup) parent).getChildAt(position));
            }
        };
    }

    // RecyclerViewMatcher class (needs to be implemented or copied)
    // You would typically have this in a separate test utility file
    public static class RecyclerViewMatcher {
        private final int recyclerViewId;

        public RecyclerViewMatcher(int recyclerViewId) {
            this.recyclerViewId = recyclerViewId;
        }

        public Matcher<View> atPosition(final int position) {
            return atPositionOnView(position, -1);
        }

        public Matcher<View> atPositionOnView(final int position, final int targetViewId) {

            return new TypeSafeMatcher<View>() {
                RecyclerView recyclerView;

                @Override
                public void describeTo(Description description) {
                    description.appendText("with id: " + recyclerViewId);
                }

                @Override
                public boolean matchesSafely(View view) {
                    this.recyclerView = (RecyclerView) view.getRootView().findViewById(recyclerViewId);
                    if (this.recyclerView == null) {
                        return false;
                    }
                    RecyclerView.ViewHolder viewHolder = this.recyclerView.findViewHolderForAdapterPosition(position);
                    if (viewHolder == null) {
                        return false;
                    }
                    View childView = viewHolder.itemView;
                    if (targetViewId == -1) {
                        return (view == childView);
                    } else {
                        return (view == childView.findViewById(targetViewId));
                    }
                }
            };
        }
    }
} 